﻿using System;
using System.Collections.Generic;
using UnityEngine;
using URandom = UnityEngine.Random;

public enum RoomDirection
{
    Up = 1 , 
    Down = 1 << 1, 
    Left = 1 << 2, 
    Right = 1 << 3
}

public class RoomGenerator
{

    GameObject _roomPrefab;
    Transform _parent;
    Vector3 _generatedPosition;

    // 房间
    public List<GameObject> Rooms { get; private set; }

    public Vector3 InitialPosition { get; set; }

    public Vector3 Offset { get; set; }


    public RoomGenerator(GameObject roomPrefab, Transform parent)
    {
        _roomPrefab = roomPrefab;
        _parent = parent;

        Rooms = new List<GameObject>();
        InitialPosition = Vector3.zero;
        Offset = new Vector3() { x = 0.155f, y = 0.075f, z = 0f};
    }


    public void Generate(int count)
    {
        Rooms.Clear();
        _generatedPosition = InitialPosition;

        for (int i=0; i<count; i++) 
        {
            GameObject room = GameObject.Instantiate(_roomPrefab, _generatedPosition, Quaternion.identity, _parent);

            ChangeRoomPosition();

            Rooms.Add(room);
        }
    }


    public void RemoveAll()
    {
        if (Rooms.Count == 0)
        {
            return;
        }

        Rooms.Clear();
        for (int i=0; i< _parent.childCount; i++)
        {
            GameObject.Destroy(_parent.GetChild(i).gameObject);
        }
    }


    void ChangeRoomPosition()
    {
        // 排除的方向
        List<RoomDirection> excludes = new List<RoomDirection>();

        Vector3 tmpPosition = Vector3.negativeInfinity;
        bool again;
        do
        {
            RoomDirection direction = RandomRoomDirection(excludes);
            switch (direction)
            {
                case RoomDirection.Up:
                    tmpPosition = _generatedPosition + new Vector3(0, Offset.y, 0);
                    break;
                case RoomDirection.Down:
                    tmpPosition = _generatedPosition + new Vector3(0, -Offset.y, 0);
                    break;
                case RoomDirection.Left:
                    tmpPosition = _generatedPosition + new Vector3(-Offset.x, 0, 0);
                    break;
                case RoomDirection.Right:
                    tmpPosition = _generatedPosition + new Vector3(Offset.x, 0, 0);
                    break;
            }
            // 判定生成的方向上是否已经存在房间
            bool isOverlap = false;
            foreach (GameObject room in Rooms)
            {
                if (room.transform.position.Equals(tmpPosition))
                {
                    isOverlap = true;
                    excludes.Add(direction);
                    break;
                }
            }
            again = isOverlap;
        } while (again);

        _generatedPosition = tmpPosition;
    }


    RoomDirection RandomRoomDirection(List<RoomDirection> excludes)
    {
        if (excludes != null && excludes.Count >= 4)
        {
            throw new ArgumentException("argument excludes length must less than 4");
        }

        List<RoomDirection> randomDirection = new List<RoomDirection>
        {
            RoomDirection.Up,
            RoomDirection.Down,
            RoomDirection.Left,
            RoomDirection.Right
        };
        if (excludes != null && excludes.Count > 0)
        {
            foreach (RoomDirection exclude in excludes)
            {
                randomDirection.Remove(exclude);
            }
        }
        
        int index = URandom.Range(0, randomDirection.Count);
        return randomDirection[index];
    }


}
